using System;
using System.Collections;
using System.Collections.Specialized;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Linq;

using MVPlan.Engine.Dive;
using MVPlan.Engine.Modeling;
using MVPlan.Engine.Segment;
using MVPlan.Engine;

using System.Drawing;

namespace MVPlan.Reporting
{
    public class SegmentReportManager
    {
        public static SegmentDataSet BuildDataSet(Profile p)
        {
            SegmentDataSet ds = new SegmentDataSet();


            BuildPrimary(ds, p);
            BuildOCBail(ds, BuildOCBailProfile(p));
            BuildContingency(ds, p);

            return ds;
        }

        protected static Profile BuildOCBailProfile(Profile p)
        {
            Profile oc = (Profile)p.Clone();

            oc.Reset();
            oc.IsOCDeco = true;
            oc.Model.Gradient.GfHigh = Prefs.Current.GfHighBailout;
            oc.Model.Gradient.GfLow = Prefs.Current.GfLowBailout;
            oc.DoDive();

            return oc;
        }

        private static StringCollection getColors(Profile p)
        {
            var stops = (from s in p.OutputSegments
                         where s.Type == SegmentType.DECO
                         select s).Count();

            StringCollection colors = new StringCollection();
            int increment = (int)255 / stops;

            for (int i = 0; i < stops; i++)
            {
                int val = 0;

                if (i != stops - 1)
                {
                    val = 255 - (i + 1) * increment;
                }

                Color c = Color.FromArgb(255, val, val);

                colors.Add("#" + c.Name.Substring(2));
            }

            return colors;
        }

        private static string getSegmentColor(SegmentAbstract s)
        {
            switch (s.Type)
            {
                case SegmentType.GASSWITCH:
                    return "#ffff66";
                default:
                    return "#FFFFFF";
            }
        }

        protected static void BuildPrimary(SegmentDataSet ds, Profile p)
        {
            SegmentDataSet.DiveSegmentDataTable t = ds.DiveSegment;

            StringCollection colors = getColors(p);

            int stopIndex = -1;

            foreach (SegmentAbstract s in p.OutputSegments)
            {
                bool add = true;

                if (s.Type == SegmentType.DECO &&
                    s.Time < Prefs.Current.ReportMinStopTime)
                {
                    add = false;
                }

                if (add &&
                    s.Type == SegmentType.ASCENT &&
                    s.Time < Prefs.Current.ReportMinStopTime)
                {
                    add = false;
                }

                if (s.Type == SegmentType.DECO) stopIndex++;

                if (add)
                {
                    SegmentDataSet.DiveSegmentRow r = t.NewDiveSegmentRow();

                    r.Depth = s.Depth;
                    r.END = s.END;
                    r.Gas = s.Gas.ShortName;
                    r.Mode = s.Mode.ToString();
                    r.RunTime = s.RunTime;
                    r.PPO2 = s.PPO2;
                    r.PPN2 = s.PPN2;
                    r.Setpoint = s.Setpoint;
                    r.Time = s.Time;
                    r.TimeMin = s.TimeMin;
                    r.TimeSec = s.TimeSec;
                    r.Type = s.Type.ToString();
                    r.TypeName = s.TypeName;
                    r.TypeString = s.TypeString;

                    if (s.Type == SegmentType.DECO && stopIndex > -1)
                        r.Color = colors[stopIndex];
                    else
                        r.Color = getSegmentColor(s);

                    t.AddDiveSegmentRow(r);
                }
            }

            SegmentDataSet.DiveInfoRow info = ds.DiveInfo.NewDiveInfoRow();

            info.ProfileIndex = 0;
            info.GfHigh = p.Model.Gradient.GfHigh;
            info.GfLow = p.Model.Gradient.GfLow;
            info.RateAscent = Prefs.Current.AscentRate;
            info.RateDescent = Prefs.Current.DescentRate;
            info.Units = Prefs.Current.Units.ToString();
            info.DepthShortString = Prefs.Current.DepthShortString;

            info.Cns = p.Model.OxTox.Cns;
            info.Otu = p.Model.OxTox.Otu;

            ds.DiveInfo.Rows.Add(info);
        }

        protected static void BuildOCBail(SegmentDataSet ds, Profile p)
        {
            SegmentDataSet.DiveSegmentOCDataTable t = ds.DiveSegmentOC;


            StringCollection colors = getColors(p);

            int stopIndex = -1;

            foreach (SegmentAbstract s in p.OutputSegments)
            {
                bool add = true;

                if (s.Type == SegmentType.DECO &&
                    s.Time < Prefs.Current.ReportMinStopTime)
                {
                    add = false;
                }

                if (add &&
                    s.Type == SegmentType.ASCENT &&
                    s.Time < Prefs.Current.ReportMinStopTime)
                {
                    add = false;
                }

                if (s.Type == SegmentType.DECO) stopIndex++;

                if (add)
                {
                    SegmentDataSet.DiveSegmentOCRow r = t.NewDiveSegmentOCRow();

                    r.Depth = s.Depth;
                    r.END = s.END;
                    r.Gas = s.Gas.ShortName;
                    r.Mode = s.Mode.ToString();
                    r.RunTime = s.RunTime;
                    r.PPO2 = s.PPO2;
                    r.PPN2 = s.PPN2;
                    r.Setpoint = s.Setpoint;
                    r.Time = s.Time;
                    r.TimeMin = s.TimeMin;
                    r.TimeSec = s.TimeSec;
                    r.Type = s.Type.ToString();
                    r.TypeName = s.TypeName;
                    r.TypeString = s.TypeString;
                    
                    if (s.Type == SegmentType.DECO && stopIndex > -1)
                        r.Color = colors[stopIndex];
                    else
                        r.Color = getSegmentColor(s);

                    t.AddDiveSegmentOCRow(r);
                }
            }

            SegmentDataSet.DiveInfoOCRow info = ds.DiveInfoOC.NewDiveInfoOCRow();

            info.ProfileIndex = 0;
            info.GfHigh = p.Model.Gradient.GfHigh;
            info.GfLow = p.Model.Gradient.GfLow;
            info.RateAscent = Prefs.Current.AscentRate;
            info.RateDescent = Prefs.Current.DescentRate;
            info.Units = Prefs.Current.Units.ToString();
            info.DepthShortString = Prefs.Current.DepthShortString;

            info.Cns = p.Model.OxTox.Cns;
            info.Otu = p.Model.OxTox.Otu;

            ds.DiveInfoOC.Rows.Add(info);
        }

        protected static void BuildContingency(SegmentDataSet ds, Profile p)
        {
            Profile pt = (Profile)p.Clone();

            //pt.InputSegments[0].Time += 5;


            pt.Reset();

            pt.Model.Gradient.GfLow = 1;
            pt.Model.Gradient.GfHigh = 1;

            pt.DoDive();

            SegmentDataSet.ContingencyRow r1 = ds.Contingency.NewContingencyRow();

            r1.Description = "GF: 100/100";
            r1.Depth = pt.InputSegments[0].Depth;
            r1.Time = pt.InputSegments[0].Time;
            r1.TTS = pt.RunTime;


            //BindingList<SegmentAbstract> stops = pt.OutputSegments.FindAll(IsDecoSegment);

            //SegmentComparer c = new SegmentComparer();

            //stops.Sort(c);

            //int max = (stops.Count < 10) ? stops.Count : 10;

            //for (int i = 0; i < max; i++)
            //{
            //    r1["Stop" + i.ToString()] = stops[i].Depth;
            //}

            ds.Contingency.Rows.Add(r1);
        }

        protected static bool IsDecoSegment(SegmentAbstract s)
        {
            return (s.Type == SegmentType.DECO);
        }
    }
}
